package burubaka.controller.mypage;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import net.arnx.jsonic.JSON;

import org.apache.commons.lang3.StringUtils;
import org.slim3.controller.Navigation;
import org.slim3.util.ApplicationMessage;

import burubaka.BurubakaConstants;
import burubaka.common.BurubakaUtil;
import burubaka.common.controller.Controller;
import burubaka.model.Handicapping;
import burubaka.model.MarkSheet;
import burubaka.model.RaceCardHorse;
import burubaka.model.RaceInfo;
import burubaka.model.Tipster;
import burubaka.service.HandicappingService;
import burubaka.service.MarkSheetService;
import burubaka.service.RaceCardHorseService;
import burubaka.service.RaceInfoService;
import burubaka.service.TipsterService;

public class BetController extends Controller {

	private static final String HORSEMARK_KEYWORD = "horsemark";
	private static final Logger log = Logger.getLogger(BetController.class.getName());
	private TipsterService tipsterService = new TipsterService();
	private RaceInfoService raceInfoService = new RaceInfoService();
	private RaceCardHorseService raceCardHorseService = new RaceCardHorseService();
	private HandicappingService handicappingService = new HandicappingService();
	private MarkSheetService markSheetService = new MarkSheetService();

	@Override
	public Navigation init() throws Exception {

		// 現在情報取得
		RaceInfo raceInfo = raceInfoService.getCurrentRaceInfo();
		if (raceInfo == null) {
			return null;
		}
		Tipster tipster = tipsterService.getTipster();
		Handicapping handicapping = handicappingService.getHandicapping(tipster.getKey(), raceInfo.getRaceDate());
		if (handicapping == null) {
			return null;
		}
		List<MarkSheet> markSheetList = markSheetService.findByAncKey(handicapping.getKey());

		Map<String, String> handicappingMap = new HashMap<String, String>();
		List<RaceCardHorse> rcList = raceCardHorseService.getRaceCardHorseList(raceInfo);
		for (RaceCardHorse raceCardHorse : rcList) {
			String key = HORSEMARK_KEYWORD + raceCardHorse.getHorseNum();
			if (raceCardHorse.getHorseNum() == handicapping.getHorseNo1()) {
				handicappingMap.put(key, BurubakaConstants.MARK_DOUBLE_CIRCLE);
			}
			if (raceCardHorse.getHorseNum() == handicapping.getHorseNo2()) {
				handicappingMap.put(key, BurubakaConstants.MARK_CIRCLE);
			}
			if (raceCardHorse.getHorseNum() == handicapping.getHorseNo3()) {
				handicappingMap.put(key, BurubakaConstants.MARK_BLACK_TRIANGULAR);
			}
			if (raceCardHorse.getHorseNum() == handicapping.getHorseNo4()) {
				handicappingMap.put(key, BurubakaConstants.MARK_TRIANGULAR);
			}
			if (raceCardHorse.getHorseNum() == handicapping.getHorseNo5()) {
				handicappingMap.put(key, BurubakaConstants.MARK_X);
			}
			if (raceCardHorse.getHorseNum() == handicapping.getHorseNo6()) {
				handicappingMap.put(key, BurubakaConstants.MARK_STAR);
			}
		}

		handicappingMap.put("commentStr", handicapping.getCommentStr());
		Map<String, Object> resMap = new HashMap<String, Object>();
		resMap.put("handicapping", handicappingMap);
		setMarkSheet(resMap, markSheetList);
		String json = JSON.encode(resMap, true);
		log.fine(json);
		setJson(json);

		return null;
	}

	/**
	 * 登録
	 * 
	 * @return Navigation
	 * @throws Exception
	 */
	public Navigation regist() throws Exception {

		// 予想家情報取得
		Tipster tipster = tipsterService.getTipster();
		String labelNickname = ApplicationMessage.get(BurubakaConstants.LABEL_NICKNAME, null);
		if (StringUtils.isEmpty(tipster.getNickname())) {
			String msg = ApplicationMessage.get(BurubakaConstants.MESSAGE_WARN_NOT_INPUT, labelNickname);
			setErrorJson(msg);
			return null;
		}

		// 現在情報取得
		RaceInfo raceInfo = raceInfoService.getCurrentRaceInfo();
		if (raceInfo == null || raceInfo.getProgress() == BurubakaConstants.PROGRESS_NOMINATION) {
			setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_INFOMATIO_BEFOR_BET, null));
			return null;
		}
		if (BurubakaUtil.isOverDeadline(raceInfo)) {
			setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_INFOMATIO_CLOSING_BET, null));
			return null;
		}

		Map<String, String> req = JSON.decode((String) reqMap.get("handicapping"), Map.class);
		Handicapping handicapping = handicappingService.getHandicapping(tipster.getKey(), raceInfo.getRaceDate());
		if (handicapping == null) {
			handicapping = new Handicapping();
			handicapping.setRaceDate(raceInfo.getRaceDate());
			handicapping.setRaceName(raceInfo.getRaceName());
		}

		Map<String, Integer> markMap = new HashMap<String, Integer>();
		// 本登録馬取得
		List<RaceCardHorse> rcList = raceCardHorseService.getRaceCardHorseList(raceInfo);
		for (RaceCardHorse raceCardHorse : rcList) {

			int no = raceCardHorse.getHorseNum();
			String key = HORSEMARK_KEYWORD + no;
			String mark = req.get(key);

			if (BurubakaConstants.MARK_DOUBLE_CIRCLE.equals(mark)) {
				// 馬1設定
				handicapping.setHorseNo1(no);
				handicapping.setHorseName1(raceCardHorse.getHorseName());
				if (markMap.get(mark) != null) {
					setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_WARN_MARK_DUPLICATE, null));
					return null;
				}
				markMap.put(mark, no);
			}

			if (BurubakaConstants.MARK_CIRCLE.equals(mark)) {
				// 馬2設定
				handicapping.setHorseNo2(no);
				handicapping.setHorseName2(raceCardHorse.getHorseName());
				if (markMap.get(mark) != null) {
					setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_WARN_MARK_DUPLICATE, null));
					return null;
				}
				markMap.put(mark, no);
			}

			if (BurubakaConstants.MARK_BLACK_TRIANGULAR.equals(mark)) {
				// 馬3設定
				handicapping.setHorseNo3(no);
				handicapping.setHorseName3(raceCardHorse.getHorseName());
				if (markMap.get(mark) != null) {
					setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_WARN_MARK_DUPLICATE, null));
					return null;
				}
				markMap.put(mark, no);
			}

			if (BurubakaConstants.MARK_TRIANGULAR.equals(mark)) {
				// 馬4設定
				handicapping.setHorseNo4(no);
				handicapping.setHorseName4(raceCardHorse.getHorseName());
				if (markMap.get(mark) != null) {
					setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_WARN_MARK_DUPLICATE, null));
					return null;
				}
				markMap.put(mark, no);
			}

			if (BurubakaConstants.MARK_X.equals(mark)) {
				// 馬5設定
				handicapping.setHorseNo5(no);
				handicapping.setHorseName5(raceCardHorse.getHorseName());
				if (markMap.get(mark) != null) {
					setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_WARN_MARK_DUPLICATE, null));
					return null;
				}
				markMap.put(mark, no);
			}

			if (BurubakaConstants.MARK_STAR.equals(mark)) {
				// 馬5設定
				handicapping.setHorseNo6(no);
				handicapping.setHorseName6(raceCardHorse.getHorseName());
				if (markMap.get(mark) != null) {
					setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_WARN_MARK_DUPLICATE, null));
					return null;
				}
				markMap.put(mark, no);
			}

		}

		if (markMap.size() < 6) {
			setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_WARN_MARK_LESS, null));
			return null;
		}

		// コメント
		handicapping.setCommentStr(req.get("commentStr"));
		handicapping.setPayOffFlag(BurubakaConstants.FLAG_ON);

		handicappingService.regist(handicapping, tipster.getKey());

		// マークシート登録
		List<MarkSheet> markSheetList = markSheetService.registMarkSheet();

		Map<String, Object> resMap = new HashMap<String, Object>();
		resMap.put(BurubakaConstants.RESPONSEKEY_MESSAGE,
				ApplicationMessage.get(BurubakaConstants.MESSAGEKEY_REG_SUCCESS, null));
		resMap.put("handicapping", req);
		setMarkSheet(resMap, markSheetList);
		String json = JSON.encode(resMap, true);
		log.fine(json);
		setJson(JSON.encode(resMap, true));
		return null;
	}

	/**
	 * 削除
	 * 
	 * @return Navigation
	 * @throws Exception
	 */
	public Navigation delete() throws Exception {
		// 現在情報取得
		RaceInfo raceInfo = raceInfoService.getCurrentRaceInfo();
		if (raceInfo == null || raceInfo.getProgress() == BurubakaConstants.PROGRESS_NOMINATION) {
			setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_INFOMATIO_BEFOR_BET, null));
			return null;
		}
		if (BurubakaUtil.isOverDeadline(raceInfo)) {
			setErrorJson(ApplicationMessage.get(BurubakaConstants.MESSAGE_INFOMATIO_CLOSING_BET, null));
			return null;
		}
		Tipster tipster = tipsterService.getTipster();
		Handicapping handicapping = handicappingService.getHandicapping(tipster.getKey(), raceInfo.getRaceDate());
		if (handicapping == null) {
			return null;
		}
		handicappingService.deleteAll(handicapping.getKey());

		Map<String, Object> resMap = new HashMap<String, Object>();
		resMap.put(BurubakaConstants.RESPONSEKEY_MESSAGE,
				ApplicationMessage.get(BurubakaConstants.MESSAGEKEY_DEL_SUCCESS, null));
		setJson(JSON.encode(resMap, true));

		return null;
	}

	/**
	 * 馬名取得
	 * 
	 * @param list
	 * @param no
	 * @return 馬名
	 */
	private String getHorseName(List<RaceCardHorse> list, int no) {
		if (list.size() < no || no == 0) {
			return "";
		}
		no = no - 1;
		RaceCardHorse raceCardHorse = list.get(no);
		if (raceCardHorse == null) {
			return "";
		}

		return raceCardHorse.getHorseName();
	}

	/**
	 * マークシート設定
	 * 
	 * @param resMap
	 * @param markSheetList
	 */
	private void setMarkSheet(Map<String, Object> resMap, List<MarkSheet> markSheetList) {
		List<MarkSheet> quinellaList = new ArrayList<MarkSheet>();
		List<MarkSheet> exactaList = new ArrayList<MarkSheet>();
		List<MarkSheet> trioList = new ArrayList<MarkSheet>();
		List<MarkSheet> trifectaList = new ArrayList<MarkSheet>();
		for (MarkSheet markSheet : markSheetList) {
			if (BurubakaConstants.BET_CLASS_QUINELLA[0].equals(markSheet.getBetClass())) {
				quinellaList.add(markSheet);
			}
			if (BurubakaConstants.BET_CLASS_EXACTA[0].equals(markSheet.getBetClass())) {
				exactaList.add(markSheet);
			}
			if (BurubakaConstants.BET_CLASS_TRIO[0].equals(markSheet.getBetClass())) {
				trioList.add(markSheet);
			}
			if (BurubakaConstants.BET_CLASS_TRIFECTA[0].equals(markSheet.getBetClass())) {
				trifectaList.add(markSheet);
			}
		}
		resMap.put("quinella", quinellaList);
		resMap.put("exacta", exactaList);
		resMap.put("trio", trioList);
		resMap.put("trifecta", trifectaList);
	}

}
